package com.szj.coroutine.project.jvm.blog2

import com.szj.coroutine.project.jvm.util.printlnThread
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.select

/*
 * 作者: 史大拿
 * 时间: 2023/2/13$ 14:53$
 */
// TODO Job 与 SupervisorJob 区别
// Job 如果子协程报错，不会执行其他协程
// SupervisorJob 子协程报错，还会接着执行其他协程
// fun main() = runBlocking<Unit>{
//    val coroutineException = CoroutineExceptionHandler { _, throwable ->
//        println("捕获到了异常:${throwable}")
//    }
//    val superJob = SupervisorJob()
//    val scope = CoroutineScope(superJob + coroutineException)
//    scope.launch {
//        printlnThread("准备出错1")
//        delay(1000)
//        throw KotlinNullPointerException("出错了1...")
//    }.join()
//
//    scope.launch {
//        printlnThread("准备出错2")
//        delay(1000)
//        throw KotlinNullPointerException("出错了2...")
//    }.join()
//
//    scope.launch {
//        printlnThread("准备出错3")
//        delay(1000)
//        throw KotlinNullPointerException("出错了3...")
//    }.join()
//}


// TODO ===================================================
// suspend fun main() {
//    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
//        printlnThread("catch 到了 $throwable")
//    }
//    val customScope =
//        // job + coroutineName + dispatcher + exception = coroutineContext
//        CoroutineScope(SupervisorJob() + CoroutineName("自定义协程") + Dispatchers.IO + exceptionHandler)
//
//    customScope.launch {// TODO 协程1
//        printlnThread("准备出错1")
//        throw KotlinNullPointerException(" ============= 出错拉 1")
//    }.join()
//
//    customScope.launch {// TODO 协程2
//        printlnThread("准备出错2")
//        throw KotlinNullPointerException(" ============= 出错拉 2")
//    }.join()
//    customScope.launch {// TODO 协程3
//        printlnThread("准备出错3")
//        throw KotlinNullPointerException(" ============= 出错拉 3")
//    }.join()
//}


// TODO ===================================================
//suspend fun main() {
//    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
//        printlnThread("catch 到了 $throwable")
//    }
//    val customScope =
//        // 我这里吧 SupervisorJob() 去掉了，免的误导大家
//        CoroutineScope(CoroutineName("自定义协程") + Dispatchers.IO + exceptionHandler)
//    customScope.launch {// TODO 协程1
//        childLaunch()
//    }.join()
//}
//private suspend fun childLaunch() = supervisorScope {
//    launch {
//        printlnThread("子协程 1")
//        delay(1000)
//        throw KotlinNullPointerException(" ============= 出错拉 1")
//    }
//    launch {
//        printlnThread("子协程 2")
//        delay(2000)
//        throw KotlinNullPointerException(" ============= 出错拉 2")
//    }
//}


// TODO =======================SupervisorJob 配合 async ============================
//async 也可以配合 SupervisorJob() 达到子协程出现问题,不影响兄弟协程执行,例如这样:
//suspend fun main() {
//    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
//        printlnThread("catch 到了 $throwable")
//    }
//    val customScope =
//        // SupervisorJob: 子协程出错不影响兄弟协程
//        CoroutineScope(SupervisorJob() + CoroutineName("自定义协程") + Dispatchers.IO )
//
//    val deferred1 = customScope.async {
//        printlnThread("子协程 1 start")
//        throw KotlinNullPointerException(" ============= 出错拉 1")
//        "协程1执行完成"
//    }
//
//    val deferred2 = customScope.async {
//        printlnThread("子协程 2 start")
//        throw KotlinNullPointerException(" ============= 出错拉 2")
//        "协程2执行完成"
//    }
//
//    try {
//        deferred1.await()
//    } catch (e: Exception) {
//        println("error1 e:$e")
//    }
//    try {
//        deferred2.await()
//    } catch (e: Exception) {
//        println("error2 e:$e")
//    }
//}

// TODO ====================================
suspend fun main() {
    val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
        printlnThread("catch 到了 $throwable")
    }
    val customScope =
        CoroutineScope(SupervisorJob() + CoroutineName("自定义协程") + Dispatchers.IO + exceptionHandler)

    val deferred1 = customScope.async {
        printlnThread("子协程 1 start")
        throw KotlinNullPointerException(" ============= 出错拉 1")
        "协程1执行完成"
    }

    val deferred2 = customScope.async {
        printlnThread("子协程 2 start")
        "协程2执行完成"
    }
    val deferred3 = customScope.async {
        printlnThread("子协程 3 start")
        throw KotlinNullPointerException(" ============= 出错拉 3")
        "协程3执行完成"
    }

    customScope.launch {
        supervisorScope {
            launch {
               val result =  deferred1.await()
                println("协程1 result:$result")
            }
            launch {
                val result =  deferred2.await()
                println("协程2 result:$result")
            }
            launch {
                val result =  deferred3.await()
                println("协程3 result:$result")
            }
        }
    }.join()
}
